import axios from 'axios'
import extend from 'extend'
// 公共逻辑函数
import basicTools from '../tools/basicTools.js'

// 执行restful地址修改
String.prototype.restfulFormat = function (param) {
    let that = this;
    let keys = Object.keys(param);
    if (param === undefined || param === null || keys.length === 0) {
        return that;
    }
    for (let key of keys) {
        that = that.replace(new RegExp("\\{" + key + "\\}", "g"), param[key]);
    }
    return that;
};

// 默认配置
function getDefaultConfig(){
    return {
        headers: {
            'Accept': 'application/json',
            // 'charset': 'UTF-8',
            // 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8;',
            'token': window.localStorage.getItem('token')
        }
    };
}

// http响应拦截器
axios.interceptors.response.use(data => {
    // 拦截根据不同的状态码处理做不同的逻辑处理
    basicTools.responseStatusLogicAction(data);
    return data
}, error => {
    // 拦截根据不同的状态码处理做不同的逻辑处理
    basicTools.responseStatusLogicAction(error.response);
    return error;
})

/**
 * 通过axios发送请求
 * @namespace GetData
 */
export default function (Options) {
    return {
        /**
         * GET 方法
         * @method get(urlKey, config, ..., argN)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param config 发送ajax传递的参数对象
         * @param argN 可配置无数个参数，第三个至最后的一个参数会以'/'为连接符拼至请求 url 中
         * @returns {promise} 返回promise对象
         * @example
         * axios.get('/user', {
     *   params: {
     *     ID: 12345
     *   }
     * }, path1, path2, path3...)
         */
        get: function (urlKey, config) {
            // 如果用户自定义URL，则直接使用用户自定义的URL，不使用apilist
            var args = Array.prototype.slice.apply(arguments);
            var url = Options.baseUrl + Options.apiList[urlKey] + '/' + args.slice(2, args.length).join('/');
            var _config = extend({}, getDefaultConfig(), config || {});
            if (_config.params) {
                _config = extend({}, _config, config);
            }
            else {
                _config.params = config || {};
            }
            return axios.get(url, _config);
        },

        /**
         * 用户自定义URL的GET方法
         * @method getUrl(url, config)
         * @memberof GetData
         * @param url 户自定义的URL
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        getUrl: function (url, config) {
            var _config = extend({}, getDefaultConfig(), config || {});
            if (config && config.params) {
                _config = extend({}, _config, config);
            } else {
                _config.params = config;
            }
            return axios.get(url, _config);
        },

        /**
         * 调用restful接口的GET方法
         * @method getRestful(urlKey, params)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        getRestful: function (urlKey, params, config) {
            // 如果用户自定义URL，则直接使用用户自定义的URL，不使用apilist
            var url = Options.baseUrl + Options.apiList[urlKey];
            var _config = extend({}, getDefaultConfig(), config || {});
            url = url.restfulFormat(params);
            return axios.get(url, _config);
        },

        /**
         * GET 请求的扩展方法
         * @method getRestful(urlKey, config)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param id 请求url的第一个扩展路径
         * @param child 请求url的第二个扩展路径
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        getExpend: function (urlKey, id, child, config) {
            var url = Options.baseUrl + Options.apiList[urlKey] + '/' + id + '/' + child;
            var _config = extend({}, getDefaultConfig(), config || {});
            return axios.get(url, _config);
        },

        /**
         * DELETE 方法
         * @method delete(urlKey, data, config, ..., argN)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param config 发送ajax传递的参数对象
         * @param argN  可配置无数个参数，第三个至最后的一个参数会以'/'为连接符拼至请求 url 中
         * @returns {promise} 返回promise对象
         * @example
         * axios.delete('/user', {
     *   data: {
     *     ID: 12345
     *   }
     * }, path1, path2, path3...)
         */
        delete: function (urlKey, data, config) {
            var args = Array.prototype.slice.apply(arguments);
            var url = Options.baseUrl + Options.apiList[urlKey] + '/' + args.slice(3, args.length).join('/');
            var dataType = config && config.dataType || '';
            var _data;
            var _config = extend({}, getDefaultConfig(), config || {});
            switch (dataType) {
                case 'formData':
                    _data = _toFormData(data);
                    break;
                case 'json':
                default:
                    _config.headers['Content-Type'] = 'application/json';
                    _data = data;
                    break;
            }
            _config.data = _data
            return axios.delete(url, _config);
        },

        /**
         * 用户自定义 URL 的 DELETE 方法
         * @method deleteUrl(url, config)
         * @memberof GetData
         * @param url 户自定义的URL
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        deleteUrl: function (url, data, config) {
            var _config = extend({}, getDefaultConfig(), config || {});
            if (!_config.data) {
                _config.data = data;
            }
            return axios.delete(url, _config);
        },

        /**
         * 调用 restful 接口的 DELETE 方法
         * @method deleteRestful(urlKey, config)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        deleteRestful: function (urlKey, params, config) {
            // 如果用户自定义URL，则直接使用用户自定义的URL，不使用apilist
            var url = Options.baseUrl + Options.apiList[urlKey];
            var _config = extend({}, getDefaultConfig(), config || {});
            url = url.restfulFormat(params);
            return axios.delete(url, _config);
        },

        /**
         * POST 方法
         * @method post(urlKey, data, config, ..., argN)
         * @memberof GetData
         * @param {string} urlKey - 对应API中的urlkey
         * @param {object} data - POST请求中传递的参数，根据config中的dataType字段设置格式，默认为'formData'
         * @param {object} config - POST请求的设置变量，dataType为自定义字段，设置POST请求参数的格式，可以设置为'json'、'formData'，默认为'formData'
         * @param {string} argN 可配置无数个参数，第四个至最后的一个参数会以'/'为连接符拼至请求 url 中
         * @returns {promise} 返回promise对象
         * @example
         * axios.post('/user', {
     *   data: { ID: 12345 }
     * }, path1, path2, path3...)
         */
        post: function (urlKey, data, config) {
            var args = Array.prototype.slice.apply(arguments);
            var url = Options.baseUrl + Options.apiList[urlKey] + '/' + args.slice(3, args.length).join('/');
            var dataType = config && config.dataType || '';
            var _data;
            var _config = extend({}, getDefaultConfig(), config || {});
            switch (dataType) {
                case 'formData':
                    _data = _toFormData(data);
                    break;
                case 'json':
                default:
                    _config.headers['Content-Type'] = 'application/json';
                    _data = data;
                    break;
            }
            return axios.post(url, _data, _config);
        },

        /**
         * 用户自定义 URL 的 POST 方法
         * @method postUrl(url, data, config)
         * @memberof GetData
         * @param url 户自定义的URL
         * @param data POST请求中传递的参数，根据config中的dataType字段设置格式，默认为'formData'
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        postUrl: function (url, data, config) {
            var _data;
            var _config = extend({}, getDefaultConfig(), config || {});
            _config.headers['Content-Type'] = 'application/json';
            // switch (dataType) {
            //   case 'formData':
            //     _data = _toFormData(data);
            //     break;
            //   case 'json':
            //   default:
            //     _config.headers['Content-Type'] = 'application/json';
            //     _data = data;
            //     break;
            // }
            return axios.post(url, data, _config);
        },

        /**
         * 调用 restful 接口的 POST 方法
         * @method postRestful(urlKey, data, config)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param data POST请求中传递的参数
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        postRestful: function (urlKey, params, data, config) {
            var _config = extend({}, getDefaultConfig(), config || {});
            // 如果用户自定义URL，则直接使用用户自定义的URL，不使用apilist
            var url = Options.baseUrl + Options.apiList[urlKey];
            url = url.restfulFormat(params);
            return axios.post(url, data, _config);
        },

        /**
         * PUT 方法
         * @method put(urlKey, data, config, ..., argN)
         * @memberof GetData
         * @param {string} urlKey - 对应API中的urlkey
         * @param {object} data - PUT请求中传递的参数，根据config中的dataType字段设置格式，默认为'formData'
         * @param {object} config - PUT请求的设置变量，dataType为自定义字段，设置PUT请求参数的格式，可以设置为'json'、'formData'，默认为'formData'
         * @param {string} argN 可配置无数个参数，第四个至最后的一个参数会以'/'为连接符拼至请求 url 中
         * @returns {promise} 返回promise对象
         * @example
         * axios.put('/user', {
     *   data: { ID: 12345 }
     * }, path1, path2, path3...)
         */
        put: function (urlKey, data, config) {
            var args = Array.prototype.slice.apply(arguments);
            var url = Options.baseUrl + Options.apiList[urlKey] + '/' + args.slice(3, args.length).join('/');
            var dataType = config && config.dataType || '';
            var _data;
            var _config = extend({}, getDefaultConfig(), config || {});
            switch (dataType) {
                case 'formData':
                    _data = _toFormData(data);
                    break;
                case 'json':
                default:
                    _config.headers['Content-Type'] = 'application/json';
                    _data = data;
                    break;
            }
            return axios.put(url, _data, _config);
        },

        /**
         * 用户自定义 URL 的 PUT 方法
         * @method putUrl(url, data, config)
         * @memberof GetData
         * @param url 户自定义的URL
         * @param data PUT请求中传递的参数，根据config中的dataType字段设置格式，默认为'formData'
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        putUrl: function (url, data, config) {
            var dataType = config && config.dataType || '';
            var _data;
            var _config = extend({}, getDefaultConfig(), config || {});
            switch (dataType) {
                case 'formData':
                    _data = _toFormData(data);
                    break;
                case 'json':
                default:
                    _config.headers['Content-Type'] = 'application/json';
                    _data = data;
                    break;
            }
            return axios.put(url, _data, _config);
        },

        /**
         * 调用 restful 接口的 POST 方法
         * @method putRestful(urlKey, config)
         * @memberof GetData
         * @param urlKey 对应API 中的urlkey
         * @param data POST请求中传递的参数
         * @param config 发送ajax传递的参数对象
         * @returns {promise} 返回promise对象
         */
        putRestful: function (urlKey, params, data, config) {
            // 如果用户自定义URL，则直接使用用户自定义的URL，不使用apilist
            var url = Options.baseUrl + Options.apiList[urlKey];
            url = url.restfulFormat(params);
            var _config = extend({}, getDefaultConfig(), config || {});
            return axios.put(url, data, _config);
        },

        /**
         * 多个promise并行调用
         * @method all
         * @memberof GetData
         * @example
         * axios.all(arg1, arg2, arg3...)
         *   .then(axios.spread)
         */
        all: function () {
            return axios.all.apply(null, arguments);
        },
        spread: function () {
            return axios.spread.apply(null, arguments);
        },

        /**
         * 传入多个promise的值，当请求成功之后统一反馈，做逻辑处理
         * */
        allPromise: function(promise1,promise2){
            var userPromise = Array.prototype.slice.apply(arguments);
            var promiseObj = new Promise(function(resolve, reject){
                axios.all(userPromise).then(axios.spread(function () {
                    resolve(arguments);
                }),function(){
                    reject(arguments);
                });
            });
            return promiseObj;
        },

        /**
         * 自由配置参数
         * @method axios
         * @memberof GetData
         * @param configObj 发送ajax 的配置参数
         * @returns {promise} 返回promise对象
         * @example
         * axios({
     *   method: 'post',
     *   url: '/user/12345',
     *   data: {
     *     firstName: 'Fred',
     *     lastName: 'Flintstone'
     *   }
     * });
         */
        axios: function (configObj) {
            return axios(configObj);
        },

        /**
         * 终止 ajax 请求， 如 xhr 的 abort 方法
         * @method cancel
         * @memberof GetData
         */
        cancel: function (urlKey) {
            if (!cancelTokenCollection[urlKey]) {
                return;
            }
            cancelTokenCollection[urlKey]();
        }
    }
}

// 将 JSON 格式转化为 formData
function _toFormData (data) {
    var formData = new FormData();
    //表单的值绑定formData
    for (var i in data) {
        if (data[i] !== null || data[i] !== undefined || data[i] !== 'null' || data[i] !== 'undefined') {
            formData.append(i, data[i]);
        }
    }
    return formData;
}
